#pragma once
#include <Windows.h>
namespace OgreEx
{
	class Mutex
	{
	public:

		/// Default constructor.
		inline Mutex()
		{
			InitializeCriticalSection(&mCriticalSection);
		}

		/// Destructor.
		inline ~Mutex()
		{
			DeleteCriticalSection(&mCriticalSection);
		}

		/// Locks the mutex, guaranteeing exclusive access to a protected resource associated with it.
		/// \note This is a blocking call and should be used with care to avoid deadlocks.
		inline void Lock()
		{
			EnterCriticalSection(&mCriticalSection);
		}

		/// Unlocks the mutex, releasing exclusive access to a protected resource associated with it.
		inline void Unlock()
		{
			LeaveCriticalSection(&mCriticalSection);
		}

	private:

		/// Disallowed copy constructor.
		Mutex(const Mutex &other);

		/// Disallowed assignment operator.
		Mutex &operator=(const Mutex &other);

		CRITICAL_SECTION mCriticalSection;  ///< Owned Win32 critical section object.
	};

	/// Lock object that wraps a Mutex for use with a Monitor.
	class Lock
	{
	public:

		/// Constructor.
		/// Creates a locked lock around the given boost::mutex.
		inline explicit Lock(Mutex &mutex) : mMutex(mutex)
		{
			mMutex.Lock();
		}

		inline ~Lock()
		{
			mMutex.Unlock();
		}

		/// Relocks the lock
		inline void Relock()
		{
			mMutex.Lock();
		}

		/// Unlocks the lock
		inline void Unlock()
		{
			mMutex.Unlock();
		}

	private:

		/// Disallowed copy constructor. Lock objects can't be copied.
		Lock(const Lock &other);
	    
		/// Disallowed assignment operator. Lock objects can't be assigned.
		Lock &operator=(const Lock &other);

		Mutex &mMutex;              ///< Referenced Mutex object.
	};
}